// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//  File: avtDelaunayFilter.C
// ************************************************************************* //

#include <avtDelaunayFilter.h>

#include <vtkDelaunay2D.h>
#include <vtkDelaunay3D.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPolyData.h>

// ****************************************************************************
//  Method: avtDelaunayFilter constructor
//
//  Programmer: js9 -- generated by xml2avt
//  Creation:   Wed Feb 25 11:01:51 PDT 2009
//
// ****************************************************************************

avtDelaunayFilter::avtDelaunayFilter()
{
}


// ****************************************************************************
//  Method: avtDelaunayFilter destructor
//
//  Programmer: js9 -- generated by xml2avt
//  Creation:   Wed Feb 25 11:01:51 PDT 2009
//
//  Modifications:
//
// ****************************************************************************

avtDelaunayFilter::~avtDelaunayFilter()
{
}


// ****************************************************************************
//  Method:  avtDelaunayFilter::Create
//
//  Programmer: js9 -- generated by xml2avt
//  Creation:   Wed Feb 25 11:01:51 PDT 2009
//
// ****************************************************************************

avtFilter *
avtDelaunayFilter::Create()
{
    return new avtDelaunayFilter();
}


// ****************************************************************************
//  Method:      avtDelaunayFilter::SetAtts
//
//  Purpose:
//      Sets the state of the filter based on the attribute object.
//
//  Arguments:
//      a        The attributes to use.
//
//  Programmer: js9 -- generated by xml2avt
//  Creation:   Wed Feb 25 11:01:51 PDT 2009
//
// ****************************************************************************

void
avtDelaunayFilter::SetAtts(const AttributeGroup *a)
{
    atts = *(const DelaunayAttributes*)a;
}


// ****************************************************************************
//  Method: avtDelaunayFilter::Equivalent
//
//  Purpose:
//      Returns true if creating a new avtDelaunayFilter with the given
//      parameters would result in an equivalent avtDelaunayFilter.
//
//  Programmer: js9 -- generated by xml2avt
//  Creation:   Wed Feb 25 11:01:51 PDT 2009
//
// ****************************************************************************

bool
avtDelaunayFilter::Equivalent(const AttributeGroup *a)
{
    return (atts == *(DelaunayAttributes*)a);
}


// ****************************************************************************
//  Method: avtDelaunayFilter::ExecuteData
//
//  Purpose:
//      Sends the specified input and output through the Delaunay filter.
//
//  Arguments:
//      inDR       The input data representation.
//
//  Returns:       The output data representation.
//
//  Programmer: Jeremy Meredith
//  Creation:   February 25, 2009
//
//  Modifications:
//    Eric Brugger, Wed Jul 23 12:00:27 PDT 2014
//    Modified the class to work with avtDataRepresentation.
//
// ****************************************************************************

avtDataRepresentation *
avtDelaunayFilter::ExecuteData(avtDataRepresentation *inDR)
{
    //
    // Get the VTK data set.
    //
    vtkDataSet *inDS = inDR->GetDataVTK();

    vtkDelaunay2D     *d2   = NULL;
    vtkDelaunay3D     *d3   = NULL;

    vtkDataSet *outDS = NULL;
    int dimension = -1;
    switch (atts.GetDimension())
    {
      case DelaunayAttributes::Tetrahedralization:
        dimension = 3;
        break;
      case DelaunayAttributes::Triangulation:
        dimension = 2;
        break;
      case DelaunayAttributes::Automatic:
        dimension = GetInput()->GetInfo().GetAttributes().GetSpatialDimension();
        break;
    }

    if (dimension == 2)
    {
        d2 = vtkDelaunay2D::New();
        d2->SetInputData(inDS);
        d2->Update();
        outDS = d2->GetOutput();
    }
    else if (dimension == 3)
    {
        d3 = vtkDelaunay3D::New();
        d3->SetInputData(inDS);
        d3->Update();
        outDS = d3->GetOutput();
    }
    else
    {
        EXCEPTION1(ImproperUseException, "Only supports 2- and 3-spatial "
                   "dimension data");
    }

    avtDataRepresentation *outDR = new avtDataRepresentation(outDS,
        inDR->GetDomain(), inDR->GetLabel());

    if (d2)
        d2->Delete();
    if (d3)
        d3->Delete();

    return outDR;
}

// ****************************************************************************
//  Method:  avtEdgeFilter::UpdateDataObjectInfo
//
//  Purpose:
//    Set the topological dimension appropriately.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    February 23, 2009
//
//  Modifications:
//    Brad Whitlock, Mon Apr  7 15:55:02 PDT 2014
//    Add filter metadata used in export.
//    Work partially supported by DOE Grant SC0007548.
//
// ****************************************************************************
void
avtDelaunayFilter::UpdateDataObjectInfo(void)
{
    int dimension = -1;
    switch (atts.GetDimension())
    {
      case DelaunayAttributes::Tetrahedralization:
        dimension = 3;
        break;
      case DelaunayAttributes::Triangulation:
        dimension = 2;
        break;
      case DelaunayAttributes::Automatic:
        dimension = GetInput()->GetInfo().GetAttributes().GetSpatialDimension();
        break;
    }

    GetOutput()->GetInfo().GetAttributes().SetTopologicalDimension(dimension);
    GetOutput()->GetInfo().GetAttributes().AddFilterMetaData("Delaunay");
}
